﻿/* Copyright (C) 2008 - 2011 by John Cronin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

using System.Runtime.CompilerServices;
namespace ABI
{
    [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
    sealed class SpecialTypeAttribute : System.Attribute
    { }

    [global::System.AttributeUsage(System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
    sealed class MethodAliasAttribute : System.Attribute
    {
        public MethodAliasAttribute(string alias) { }
    }

    [global::System.AttributeUsage(System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
    sealed class ExtraArgumentAttribute : System.Attribute
    {
        public ExtraArgumentAttribute(int arg_no, int base_type) { }
    }

    [global::System.AttributeUsage(System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
    sealed class AlwaysCompileAttribute : System.Attribute
    { }

    [global::System.AttributeUsage(System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
    sealed class SyscallAttribute : System.Attribute
    { }

    [global::System.AttributeUsage(System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    sealed class ISRAttribute : System.Attribute
    { }

    [global::System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Enum, Inherited = false, AllowMultiple = true)]
    sealed class OutputCHeaderAttribute : System.Attribute
    { }

    [global::System.AttributeUsage(System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    sealed class ProfileAttribute : System.Attribute
    {
        public ProfileAttribute(bool profile) { }
    }

    [System.AttributeUsage(System.AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
    sealed class VTableAliasAttribute : System.Attribute
    {
        public VTableAliasAttribute(string alias) { }
    }

    [System.AttributeUsage(System.AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
    sealed class TypeInfoAliasAttribute : System.Attribute
    {
        public TypeInfoAliasAttribute(string alias) { }
    }

    class MemoryOperations
    {
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern byte PeekU1(ulong addr);
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern ushort PeekU2(ulong addr);
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern uint PeekU4(ulong addr);
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern ulong PeekU8(ulong addr);
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern void Poke(ulong addr, byte b);
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern void Poke(ulong addr, ushort v);
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern void Poke(ulong addr, uint v);
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern void Poke(ulong addr, ulong v);
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void QuickClearAligned16(ulong addr, ulong size);
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal unsafe static extern void * GetInternalArray(System.Array array);
    }

    class IoOperations
    {
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern void PortOut(ushort port, byte v);
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
        internal static extern byte PortInb(ushort port);
    }

    class CastOperations
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern Multiboot.Header ReinterpretAsMboot(ulong addr);

        [MethodImpl(MethodImplOptions.InternalCall)]
        unsafe internal static extern tysos.x86_64.Tss.Tss_struct* ReinterpretAsTssStruct(ulong addr);

        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern ulong GetArg0U8();
    }

    class OtherOperations
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void Halt();

        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern ulong ReadCR3();
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void WriteCR3(ulong val);
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern ulong ReadCR4();
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void WriteCR4(ulong val);
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern ulong ReadCR0();
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void WriteCR0(ulong val);
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern ulong ReadCR2();
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void WriteCR2(ulong val);

        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void Lidt(ulong addr, ushort limit);
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void Ltr(ulong selector);

        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern uint ReadMxcsr();
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void WriteMxcsr(uint val);

        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern ulong RdMsr(uint reg_no);
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal static extern void WrMsr(uint reg_no, ulong val);

        [MethodImpl(MethodImplOptions.InternalCall)]
        private static unsafe extern void _Cpuid(uint req_no, uint* buf);

        internal static uint[] Cpuid(uint req_no)
        {
            uint[] buf = new uint[4];

            unsafe
            {
                _Cpuid(req_no, (uint*)ABI.MemoryOperations.GetInternalArray(buf));
            }

            return buf;
        }

        [MethodImpl(MethodImplOptions.InternalCall)]
        internal extern unsafe static void switch_task(ulong* old_rsp, ulong new_rsp);
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal extern static ulong GetRBP();
        [MethodImpl(MethodImplOptions.InternalCall)]
        internal extern static ulong RdTsc();

        [MethodImpl(MethodImplOptions.InternalCall)]
        internal extern static void Sti();
    }
}
